/** 
* Projet AP5 - Agenda PDA
* AgendaEngine.java
*/

package pda.datas;
import java.io.*;


import java.util.Date;

import java.io.Serializable;
import java.io.File;

import java.text.DateFormat;
import java.text.SimpleDateFormat;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.ArrayList;

import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;

/** Classe qui permet la gestion des evenements, par la sauvegarde,
* le chargement, l'ajout, la suppression, et l'existence de ces evenements
*/

public class AgendaEngine implements Serializable {
    
//##########################################################################################################
//										Attributs
//##########################################################################################################

	/** ID de numero de  version non modifiable */
	private static final long serialVersionUID = 42L;
	
	/** HashMap d'un String et d'une ArrayList pour un evenement */
 	private HashMap<String, ArrayList<Activite>> evtJour;

	/** HashMap d'un String et d'une ArrayList pour un evenement avec repetition */
	private HashMap<String, ArrayList<Activite>> evtJourAvecRepet;

	
//##########################################################################################################
//										Constructeur
//##########################################################################################################

    	/**
	* Le constructeur de la classe
	*/
	public AgendaEngine(){
		evtJourAvecRepet = new HashMap<String, ArrayList<Activite>>();
		evtJour = new HashMap<String, ArrayList<Activite>>();
	}


//##########################################################################################################
//										Methodes 
//##########################################################################################################


	/**
	* Verifie l'existence d'une activite pour eviter la superposition
	* @param arr l'ArrayList des activite
	* @param heurD l'heure de debut
	* @param heurF l'heure de fin
	* @param minuD les minutes de l'heure de debut
	* @param minuF les minutes de l'heure de fin
	* @param motif le motif
	*/
	public boolean checkSuperposition(ArrayList<Activite> arr, String heurD, String heurF, String minuD, String minuF, String motif){
		boolean ret = false;
		if (!( Integer.parseInt(heurD) > 24 || Integer.parseInt(heurF) > 24 || Integer.parseInt(heurD) < 0 || Integer.parseInt(heurF ) < 0 || Integer.parseInt(minuD) > 60 || Integer.parseInt(minuF) > 60 || Integer.parseInt(minuD) < 0 || Integer.parseInt(minuF) < 0 )){
			
			for (Activite act : arr){
				// evt apres l'autre
				if ( Integer.parseInt(heurD) > Integer.parseInt(act.getHeureFin()) ){
					ret = true;
				//evt avant lautre
				}else if ( Integer.parseInt(heurF) < Integer.parseInt(act.getHeureDeb()) ){
					ret = true;
				//evt dans la mm heure apres 
				} else if (Integer.parseInt(heurD) == Integer.parseInt(act.getHeureFin()) && Integer.parseInt(minuD) > Integer.parseInt(act.getMinuteFin())){
					ret = true;
				//evt dans la mm heure avant
				} else if (Integer.parseInt(heurF) == Integer.parseInt(act.getHeureDeb()) && Integer.parseInt(minuF) < Integer.parseInt(act.getMinuteDeb())){
					ret = true;
				} else if (motif.equals(act.getMotif())){
					ret = true;
				}
				
			}
		}
		return ret ;
	}
	

	//activite
    	/**
	* Ajouts d'une activite
	* @param date la date 
	* @param motif le motif
	* @param heurD l'heure de debut
	* @param minuD les minutes de l'heure de debut
	* @param heurF l'heure de fin
	* @param minuF les minutes de l'heure de fin  
	* @param repetition le nombre de repetition
	*/
	public String addActivite(String date, String motif, String heurD, String minuD, String heurF, String minuF, int repetition){
	
		String ret = "";
		if ( motif.length() != 0 && !heurD.contains(" ") && !heurF.contains(" ") && !minuD.contains(" ") && !minuF.contains(" ") ) {
			
			if ( Integer.parseInt(heurD) < 0 || 
				Integer.parseInt(heurD) > 23 ||
				Integer.parseInt(heurF) < 0  ||
				Integer.parseInt(heurF) > 23 ||
				Integer.parseInt(heurD) > Integer.parseInt(heurF) ||
				Integer.parseInt(minuD) < 0  ||
				Integer.parseInt(minuD) > 59 ||
				Integer.parseInt(minuF) < 0  ||
				Integer.parseInt(minuF) > 59 ||
				(Integer.parseInt(heurD) == Integer.parseInt(heurF) && Integer.parseInt(minuD) > Integer.parseInt(minuF)  )){
					ret = "improbable";	
					
			}else {	
				if ( this.getEvtExiste(date) ){
					ArrayList<Activite> arr = evtJour.get(date);
					if ( checkSuperposition(arr, heurD, heurF, minuD, minuF, motif) ){
						ArrayList<Activite> array = evtJour.get(date);
						array.add(new Activite(motif, heurD, heurF, minuD, minuF) );						
						ret = "ok" ;
					} else {
						ret = "superposition" ;
					}
				}else {
					Activite act = new Activite(motif, heurD, heurF, minuD, minuF);
					ArrayList<Activite> array = new ArrayList<Activite>() ;
					array.add(act);
					evtJour.put(date, array) ;
					ret = "ok" ;
					if (repetition != 0 ){
						if (evtJourAvecRepet.containsKey(date)){
								ArrayList<Activite> array2 = evtJourAvecRepet.get(date);
								array2.add(new Activite(motif, heurD, heurF, minuD, minuF) );
								
							
						}else {
							Activite act2 = new Activite(motif, heurD, heurF, minuD, minuF);
							ArrayList<Activite> array2 = new ArrayList<Activite>() ;
							array2.add(act2);
							evtJourAvecRepet.put(date, array2) ;
						}
					}
				}
			}
		}else{
			ret = "incomplet";
		}
		
		return ret;
	}
	
	//reunion
    	/**
	* Ajouts d'une reunion
	* @param date la date 
	* @param motif le motif
	* @param heurD l'heure de debut
	* @param minuD les minutes de l'heure de debut
	* @param heurF l'heure de fin
	* @param minuF les minutes de l'heure de fin  
	* @param repetition le nombre de repetition
	* @param lieu le lieu
	* @param initiateur l'inititeur de l'evenement
	* @param invite l'invite
	* @param mail le mail
	* @param duree la duree de l'evenement
	*/
	public String addActivite(String date, String motif, String heurD, String minuD, String heurF, String minuF, int repetition, String lieu, String initiateur, String invite, String mail, String duree )	{
		String ret = "";
		if ( motif.length() != 0 && heurD.length() != 0 && heurF.length() != 0 && minuD.length() != 0 && minuF.length() != 0) {
			if ( Integer.parseInt(heurD) < 0 || 
				Integer.parseInt(heurD) > 23 ||
				Integer.parseInt(heurF) < 0  ||
				Integer.parseInt(heurF) > 23 ||
				Integer.parseInt(heurD) > Integer.parseInt(heurF) ||
				Integer.parseInt(minuD) < 0  ||
				Integer.parseInt(minuD) > 59 ||
				Integer.parseInt(minuF) < 0  ||
				Integer.parseInt(minuF) > 59 ||
				(Integer.parseInt(heurD) == Integer.parseInt(heurF) && Integer.parseInt(minuD) > Integer.parseInt(minuF)  )){
					ret = "improbable";	
			}else {	
				if ( this.getEvtExiste(date) ){
					ArrayList<Activite> arr = evtJour.get(date);
					if ( checkSuperposition(arr, heurD, heurF, minuD, minuF, motif) ){
						ArrayList<Activite> array = evtJour.get(date);
						array.add(new Reunion(motif, heurD, heurF, minuD, minuF, lieu, initiateur, invite, mail, duree) );
						ret = "ok" ;
					} else {
						ret = "superposition" ;
					}
				}else {
					
					Activite act = new Reunion(motif, heurD, heurF, minuD, minuF, lieu, initiateur, invite, mail, duree);
					ArrayList<Activite> array = new ArrayList<Activite>() ;
					array.add(act);
					evtJour.put(date, array) ;
					ret = "ok" ;
					if (repetition != 0 ){
						if (evtJourAvecRepet.containsKey(date)){
								ArrayList<Activite> array2 = evtJourAvecRepet.get(date);
								array2.add(new Reunion(motif, heurD, heurF, minuD, minuF, lieu, initiateur, invite, mail, duree) );
								
							
						}else {
							Activite act2 = new Reunion(motif, heurD, heurF, minuD, minuF, lieu, initiateur, invite, mail, duree);
							ArrayList<Activite> array2 = new ArrayList<Activite>() ;
							array2.add(act2);
							evtJourAvecRepet.put(date, array2) ;
						}
					}
				}
			}
		}else{
			ret = "incomplet";
		}
		return ret;
	
	}
	
	//cours
    	/**
	* Ajouts d'un cours
	* @param date la date 
	* @param motif le motif
	* @param heurD l'heure de debut
	* @param minuD les minutes de l'heure de debut
	* @param heurF l'heure de fin
	* @param minuF les minutes de l'heure de fin  
	* @param repetition le nombre de repetition
	* @param lieu le lieu
	* @param prof le professeur
	* @param matiere la matiere
	*/
	public String addActivite(String date, String motif, String heurD, String minuD, String heurF, String minuF, int repetition, String lieu, String prof, String matiere)	{
		String ret = "";
		if ( motif.length() != 0 && heurD.length() != 0 && heurF.length() != 0 && minuD.length() != 0 && minuF.length() != 0) {
			if ( Integer.parseInt(heurD) < 0 || 
				Integer.parseInt(heurD) > 23 ||
				Integer.parseInt(heurF) < 0  ||
				Integer.parseInt(heurF) > 23 ||
				Integer.parseInt(heurD) > Integer.parseInt(heurF) ||
				Integer.parseInt(minuD) < 0  ||
				Integer.parseInt(minuD) > 59 ||
				Integer.parseInt(minuF) < 0  ||
				Integer.parseInt(minuF) > 59 ||
				(Integer.parseInt(heurD) == Integer.parseInt(heurF) && Integer.parseInt(minuD) > Integer.parseInt(minuF)  )){
					ret = "improbable";	
			}else {	
				if ( this.getEvtExiste(date) ){
					ArrayList<Activite> arr = evtJour.get(date);
					if ( checkSuperposition(arr, heurD, heurF, minuD, minuF, motif) ){
						ArrayList<Activite> array = evtJour.get(date);
						array.add(new Cours(motif, heurD, heurF, minuD, minuF, lieu, prof, matiere) );
						ret = "ok" ;
					} else {
						ret = "superposition" ;
					}
				}else {
					
					Activite act = new Cours(motif, heurD, heurF, minuD, minuF, lieu, prof, matiere);
					ArrayList<Activite> array = new ArrayList<Activite>() ;
					array.add(act);
					evtJour.put(date, array) ;
					ret = "ok" ;
					if (repetition != 0 ){
						if (evtJourAvecRepet.containsKey(date)){
								ArrayList<Activite> array2 = evtJourAvecRepet.get(date);
								array2.add(new Cours(motif, heurD, heurF, minuD, minuF, lieu, prof, matiere) );
								
							
						}else {
							Activite act2 = new Cours(motif, heurD, heurF, minuD, minuF, lieu, prof, matiere);
							ArrayList<Activite> array2 = new ArrayList<Activite>() ;
							array2.add(act2);
							evtJourAvecRepet.put(date, array2) ;
						}
					}
				}
			}
		}else{
			ret = "incomplet";
		}
		return ret;
	
	
	}
	
	//rdv
    	/**
	* Ajouts d'un rendez-vous
	* @param date la date 
	* @param motif le motif
	* @param heurD l'heure de debut
	* @param minuD les minutes de l'heure de debut
	* @param heurF l'heure de fin
	* @param minuF les minutes de l'heure de fin  
	* @param repetition le nombre de repetition
	* @param lieu le lieu
	* @param invite l'invite
	*/
	public String addActivite(String date, String motif, String heurD, String minuD, String heurF, String minuF, int repetition, String lieu, String invite){
		String ret = "";
		if ( motif.length() != 0 && heurD.length() != 0 && heurF.length() != 0 && minuD.length() != 0 && minuF.length() != 0) {
			if ( Integer.parseInt(heurD) < 0 || 
				Integer.parseInt(heurD) > 23 ||
				Integer.parseInt(heurF) < 0  ||
				Integer.parseInt(heurF) > 23 ||
				Integer.parseInt(heurD) > Integer.parseInt(heurF) ||
				Integer.parseInt(minuD) < 0  ||
				Integer.parseInt(minuD) > 59 ||
				Integer.parseInt(minuF) < 0  ||
				Integer.parseInt(minuF) > 59 ||
				(Integer.parseInt(heurD) == Integer.parseInt(heurF) && Integer.parseInt(minuD) > Integer.parseInt(minuF)  )){
					ret = "improbable";	
			}else {	
				if ( this.getEvtExiste(date) ){
					ArrayList<Activite> arr = evtJour.get(date);
					if ( checkSuperposition(arr, heurD, heurF, minuD, minuF, motif) ){
						ArrayList<Activite> array = evtJour.get(date);
						array.add(new Rdv(motif, heurD, heurF, minuD, minuF, lieu, invite) );
						ret = "ok" ;
					} else {
						ret = "superposition" ;
					}
				}else {
					
					Activite act = new Rdv(motif, heurD, heurF, minuD, minuF, lieu, invite);
					ArrayList<Activite> array = new ArrayList<Activite>() ;
					array.add(act);
					evtJour.put(date, array) ;
					ret = "ok" ;
					if (repetition != 0 ){
						if (evtJourAvecRepet.containsKey(date)){
								ArrayList<Activite> array2 = evtJourAvecRepet.get(date);
								array2.add(new Rdv(motif, heurD, heurF, minuD, minuF, lieu, invite) );
								
							
						}else {
							Activite act2 = new Rdv(motif, heurD, heurF, minuD, minuF, lieu, invite);
							ArrayList<Activite> array2 = new ArrayList<Activite>() ;
							array2.add(act2);
							evtJourAvecRepet.put(date, array2) ;
						}
					}
				}
			}
		}else{
			ret = "incomplet";
		}
		return ret;
	
	}

	/**
	* Methode qui permet la suppression d'un evenement
	* @param motif le motif de l'evenement
	* @param date la date de l'evenement
	*/
	public void deleteEvt(String motif, String date){		
		Activite aRetirerAussi = null;
		
		if (evtJourAvecRepet.containsKey(date)){
			ArrayList<Activite> array2 = evtJourAvecRepet.get(date);
			for (Activite uneAct : array2) {
				if ( motif.equals(uneAct.getMotif() ) ){
					aRetirerAussi = uneAct;
				}
			}
			array2.remove(aRetirerAussi);
			evtJourAvecRepet.remove(date);
			if (array2.size() != 0 ){evtJourAvecRepet.put(date, array2);}
		}
		
		ArrayList<Activite> array = evtJour.get(date);
		
		Activite aRetirer = null;
		for (Activite uneAct : array) {
			if ( motif.equals(uneAct.getMotif() ) ){
				aRetirer = uneAct;
			}
		}
		
		array.remove(aRetirer);

		evtJour.remove(date);
		if (array.size() != 0 ){evtJour.put(date, array);}
	}
	
	/**
	* Methode qui permet la suppression de touts les evenements creer
	*/
	public void deleteAllEvt(){
		evtJour.clear(); 
		evtJourAvecRepet.clear();
	}
	
	/**
	* Methode qui permet la suppression du dernier evenement
	* @param date la date de l'evenement
	*/	
	public void deletePreviousEvt(String date){
		Set<String> cle = evtJour.keySet();
		Iterator it = cle.iterator();
		ArrayList<String> toErase = new ArrayList<String>();

		while ( it.hasNext() ) {
			String tmp = (String)it.next();
			if ( dateAnterieur(tmp, date) ){
				toErase.add(tmp);
			}
		}
		for (String tmpp : toErase)
			evtJour.remove(tmpp);
		

	}
	
	/**
	* Retourne un booleen pour la date precedente
	* @param tmp la chaine de caractère temporaire
	* @param date la date
	* 
	*@return ret Le booleen 
	*/
	public boolean dateAnterieur(String tmp, String  date){
		boolean ret = false;
		String[] tab1 = tmp.split("/");
		String[] tab2 = (date.split(" ")[1]).split("/");
		if( Integer.parseInt(tab1[2]) <= Integer.parseInt(tab2[2]) && Integer.parseInt(tab1[1]) <= Integer.parseInt(tab2[1]) && Integer.parseInt(tab1[0]) <= Integer.parseInt(tab2[0]) ){
			ret = true ;
		}
		return ret ;
	}
	
	/**
	* Retourne l'HashMap
	* @return evtJour */
	public  HashMap<String, ArrayList<Activite>> getHash(){ return evtJour ; }
	
	/**
	* Permet de charger tout les evenements
	* @param path
	*/
	public void charger (String path){
	    if (path == null ) path = "agendaDefault";
	    try{
            
		FileInputStream in = new FileInputStream ("data/sauvegarde/"+path);
		ObjectInputStream flux = new ObjectInputStream (in);
		AgendaEngine tmp = (AgendaEngine)flux.readObject();
		this.evtJour = tmp.evtJour;
		this.evtJourAvecRepet = tmp.evtJourAvecRepet;
			
	    }
	    catch (IOException e){
		System.out.println("Engine_charger1 "+e.getMessage());
	    }
	    catch (ClassNotFoundException e){
		System.out.println("Engine_charger2 "+e.getMessage());
	    }
	}

	/**
	* Permet de sauvegarder tout les evenements
	* @param path
	*/
	public void sauver (String path){
	    if (path == null ) path = "agendaDefault";
	    try{
		FileOutputStream out = new FileOutputStream ("data/sauvegarde/"+path);
		ObjectOutputStream flux = new ObjectOutputStream (out);
		flux.writeObject (this);
	    }
	    catch (FileNotFoundException e){
		System.out.println ("Engine_sauver1 "+e.getMessage ());
	    }catch (IOException e){
            System.out.println ("Engine_sauver2 "+e.getMessage ());
        }
    }

//##########################################################################################################
//										Methodes Get
//##########################################################################################################
	
	/**
	* Retourne l'ArrayList de l'evenements a partir de la date
	* @param date la date de l'evenement
	*/
	public ArrayList<String> getEvt(String date){
		ArrayList<Activite> tmp ;
		ArrayList<String> disp = new ArrayList<String>();

		int i = 0;

		if ( evtJour.containsKey(date) ) {
		tmp = evtJour.get(date);
			for ( Activite act : tmp){
				try {
					String tmpp = (act.getMotif().length() > 30 ) ? act.getMotif().substring(0,30): act.getMotif() ;
					disp.add(tmpp);
					i++;
				}catch (Exception exce){
					disp.add("<html>( erreur d'entr&eacute;e )</html>");
				}
			}
		}
		if (i < 1 ){
			disp.add("<html>( aucune entr&eacute;e )</html>");
		}
		
		return  disp ;
	}
	
	/**
	* Retourne si l'evenement est existant ou non
	* @param date la date de l'evenement 
	*/
	public boolean getEvtExiste(String date){
		return evtJour.containsKey(date) ;
	}
	
	/**
	* Retourne l'ArrayList avec les informations de l'evenement
	* @param date la date rechercher
	* @param motif le motif de l'evenement
	* @return la disponibilité de l'evenement
	*/
	public ArrayList<String> getEvtOnClick(String date, String motif){
		ArrayList<Activite> tmp = evtJour.get(date);
		ArrayList<String> disp = new ArrayList<String>();
		for ( Activite act : tmp){
			String tmpp = (act.getMotif().length() > 30 ) ? act.getMotif().substring(0,30): act.getMotif() ;
			if (tmpp.equals(motif) ){
				disp = act.getInArray() ;
			}		
		}
			
		return  disp ;
	
	}
} 
